﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using Fintech.Utils;
using Fintech.Utils.Database;

namespace ZOVNP.Model.Abstracts
{
    /// <summary>
    /// Интерфейс движка хранилища данных. Хранилище данных работает с объектами, существующими в предметной области приложения Skif. Все объекты из
    /// этой области реализуют интерфейс IDomain. Есть и методы для работы с нетипизированными плоскими наборами данных.
    /// </summary>
    [System.ComponentModel.Description("Интерфейс движка хранилища доменных объектов")]
    public interface IDomainEngine : IEngine, IRequestable
    {
        #region Свойства

        /// <summary> Поддерживает ли движок сбор статистики о своей работе. </summary>
        bool StatisticsEnabled { get; }
        
        /// <summary> Метаданные движка. </summary>
        IEngineMetadata Metadata { get; }

        /// <summary> Получить объект, предоставляющий методы, отвечающие за безопасность. </summary>
        IZOVNPSecurityProvider SecurityProvider { get; }
        
        /// <summary> Получить объект, предоставляющий методы, отвечающие за безопасность. </summary>
        IDbParameterProvider ParameterProvider { get; }

        IEngineGetter Getter { get; }

        IEngineAdder Adder { get; }

        IEngineRemover Remover { get; }
        
        /// <summary> Получить текущего пользователя </summary>
        /// <value> объект "пользователь"</value>
        IUser CurrentUser { get; }
        /// <summary> Получить менеджер настроек. </summary>
        //ISettingsManager SettingsManager { get; }
        /// <summary> Событие о необходимости изменения пароля. </summary>
        event PasswordChangingEventHandler PasswordChanging;

        #endregion

        #region Exists

        /// <summary> Проверка существования доменных объектов в хранилище. </summary>
        /// <typeparam name="InterfaceType"> Тип проверяемых объектов. </typeparam>
        /// <param name="Items"> Список проверяемых объектов. </param>
        /// <returns> Массив булевых значений, каждое из которых указывает, существует ли соответствующий объект в хранилище. </returns>
        bool[] Exists<InterfaceType>(params InterfaceType[] Items) where InterfaceType : IDomainObject;

        /// <summary> Проверка существования доменных объектов в хранилище. </summary>
        /// <typeparam name="InterfaceType"> Тип проверяемых объектов. </typeparam>
        /// <param name="Keys"> Список идентификаторов проверяемых объектов. </param>
        /// <returns> Массив булевых значений, каждое из которых указывает, существует ли соответствующий объект в хранилище. </returns>
        bool[] Exists<InterfaceType>(params Guid[] Keys) where InterfaceType : IDomainObject;

        /// <summary> Проверка существования всех заданных доменных объектов в хранилище. </summary>
        /// <typeparam name="InterfaceType"> Тип проверяемых объектов. </typeparam>
        /// <param name="Items"> Список проверяемых объектов. </param>
        /// <returns> True, если все указанные в списке объекты существуют в хранилище, иначе false. </returns>
        bool ExistsAll<InterfaceType>(params InterfaceType[] Items) where InterfaceType : IDomainObject;

        /// <summary> Проверка существования всех заданных доменных объектов в хранилище. </summary>
        /// <typeparam name="InterfaceType"> Тип проверяемых объектов. </typeparam>
        /// <param name="Keys"> Список идентификаторов проверяемых объектов. </param>
        /// <returns> True, если все указанные в списке объекты существуют в хранилище, иначе false. </returns>
        bool ExistsAll<InterfaceType>(params Guid[] Keys) where InterfaceType : IDomainObject;

        #endregion

        #region Other

        /// <summary> Создание вспомогательного соединения с источником данных. </summary>
        /// <returns> Созданное вспомогательное соединение с источником данных. </returns>
        DbConnection CreateAuxiliaryConnection();

        /// <summary> Создание вспомогательного объекта для выполнения запросов к источнику данных. </summary>
        /// <param name="Connection"> Используемое соединение, null для использования текущего соединения. </param>
        /// <returns> Объект, реализующий интерфейс исполнения запросов. </returns>
        IQueryExecutor CreateExecutor(DbConnection Connection);

        event EventHandler CacheUpdated;
        
        void Log(string OperationCode, string ObjectCode, Guid ObjectID, Guid? ParentObjectID = null, string Comment = null);

        /// <summary> Получить число текущих открытых транзакций. </summary>
        /// <returns> Число транзакций. </returns>
        int GetTransactionCount();

        /// <summary> Получение статистики использования движка. </summary>
        /// <returns> Словарь со статистической информацией. </returns>
        IDictionary RetrieveStatistics();

        /// <summary> Определить, относится ли возникшее исключение к категории пользовательских (специальных) ошибок, а не системных ошибок. </summary>
        /// <param name="Error"> Проверяемое исключение. </param>
        /// <returns> true, если исключение является специальной ошибой, иначе false (системная ошибка) </returns>
        bool IsUserDefinedError(Exception Error);

        /// <summary> Проверить пригодность значения свойства для заданного типа доменного объекта. </summary>
        /// <param name="InterfaceType"> Интерфейсный тип доменного объекта. </param>
        /// <param name="PropertyName"> Имя свойства, для которого делается проверка значения. </param>
        /// <param name="Value"> Проверяемое значение свойства. </param>
        /// <param name="Context"> Контекст проверки. </param>
        /// <param name="Explanation"> Поясняющее сообщение об ошибке, если метод вернул false. </param>
        /// <returns> True в случае успешности проверки, иначе false. </returns>
        bool CheckPropertyValue(Type InterfaceType, string PropertyName, object Value, object Context, out string Explanation);
        
        /// <summary> Сгенерировать уникальный идентификатор. </summary>
        /// <returns> Уникальный идентификатор. </returns>
        Guid NewGuid();

        /// <summary> Получить текущую серверную дату. </summary>
        /// <returns> Текущая дата по серверному времени. </returns>
        DateTime GetCurrentDateTime();

        /// <summary> Создание контекста работы с доменными объектами. </summary>
        /// <param name="CommandTimeout"> Значение таймаута в секундах на выполнение запросов к хранилищу. Null для значения по умолчанию. </param>
        /// <returns> Контекст-песочница. </returns>
        IDomainContext CreateContext(int? CommandTimeout = null);
        
        /// <summary> Открыть транзакцию к хранилищу данных. </summary>
        /// <param name="TransactionName"> Необязательное название транзакции. </param>
        /// <returns> Объект-транзакция, которую после выполнения команд транзакции следует либо зафиксировать, либо откатить. </returns>
        ITransaction BeginTransaction(string TransactionName = null);

        #endregion
    }
}
